ART是一个C++程序。用于执行dex字节码,也兼容JVM字节码。其直接运行在linux上。不存在ART运行在JVM上的说法。

JVM提供了JNI来在Native层次上操纵JVM(包括启动JVM)。C/C++可以通过JavaVM实例来操作JVM。对应的,ART也提供了一套JNI接口,相应的函数从libart.so中加载,是相对独立的接口,而不是直接使用java的JNI库。对应JavaVM的是JavaVMExt,用来代表一个ART实例。

手机运行的是linux系统。linux系统中第一个进程init可以通过读取配置脚本执行脚本命令。在android手机中,init的配置脚本为启动/system/bin/app_process。

app_process用于启动ART,并在ART上运行一个java程序。当启动Zygote时,这个java程序是com.android.internal.os.ZygoteInit

语句是:

if (zygote) {
        runtime.start("com.android.internal.os.ZygoteInit", args, zygote);
    }

其中,runtime的定义是:

AppRuntime runtime(argv[0], computeArgBlockSize(argc, argv));

AppRuntime的类型是:

class AppRuntime : public AndroidRuntime

所以,runtime.start为:

/*
 * Start the Android runtime.  This involves starting the virtual machine
 * and calling the "static void main(String[] args)" method in the class
 * named by "className".
 *
 * Passes the main function two arguments, the class name and the specified
 * options string.
 */
void AndroidRuntime::start(const char* className, const Vector<String8>& options, bool zygote) {
    //...
    JniInvocation jni_invocation; 
    jni_invocation.Init(NULL);  // 从libart.so中取出三个函数并保存,最重要的是JNI_CreateJavaVM
    JNIEnv* env; 
    startVm(&mJavaVM, &env, zygote) // 启动VM
    //...
}

附:JNI(Java Native Interface)提供了java和C/C++互操作的接口, 详见https://www3.ntu.edu.sg/home/ehchua/programming/java/JavaNativeInterface.html#zz-3.

总而言之,这个过程启动了预热好的ART虚拟机(所谓预热是指提前将常用的java类加载进内存)。最后得到一个在ART上运行的Zygote进程。

每一个Android进程都需要运行在一个独立的ART实例上。每当用户需要启动一个新进程时,launcher就将信息发送到zygote进程,由zygote在linux上fork自身产生一个新的ART实例并启动进程。当然可以让linux系统从启动ART开始启动一个新进程,但ART启动和预热都需要时间,fork可以节省时间。

Insight:如果多个程序都需要同一个内存资源,可以通过fork复用。